[CloudFront + S3]特定バケットに特定ディストリビューションのみからアクセスできるよう設定する
皆さんこんにちは、yokatsukiです。
静的コンテンツの配信性能を高めるために、S3とCloudFrontを組み合わせて、CloudFrontからコンテンツを配信する形態は、Cache Distributionパターンとしてよく知られています。しかし、設定がよく理解できていないために、CroudFront以外に、S3コンテンツへ直接アクセスできるようになっていませんか?しかし具体的な設定方法をネットで調べても、(2014年9月初めの時点では)署名付きURL等のやや複雑な説明ばかりで、「配信できているからいいや」と設定をおざなりにしている方、多いと思います。
今回は、S3バケット上のコンテンツを、特に署名や期限等の複雑な設定を設けず、シンプルにCloudFrontのみからアクセスできるように設定する方法を紹介します。上記Cache Distributionパターンのシンプルな一例と考えて下さい。
下図が構成イメージです。配信元であるCloudFrontディストリビューションにオリジンアクセスアイデンティティを作成し、S3のバケットポリシーとしてそのオリジンアクセスアイデンティティからのリクエストだけ受け付ける設定にする、というところがポイントになります。
詳細は下記AWSドキュメントに記載がありますので、是非ご一読ください。
【参考】オリジンアクセスアイデンティティを使用して Amazon S3 コンテンツへのアクセスを制限する - Amazon CloudFront 開発者ガイド (API Version 2014-01-31)
実装手順
S3バケットの設定
S3バケット作成
まずは、コンテンツの格納先S3バケットを作成します。AWS Management Consoleから、S3をクリックします。
バケットを新規作成します。Create Bucketをクリックします。
バケット名を付けます。今回はcm-katsukiとします。
バケットcm-katsukiが作成されました。Propertiesをクリックすると、バケットポリシーは今のところ設定されていない("Add Bucket Policy"と表示されている)ことが確認できます。
コンテンツアップロード
バケットに、テスト用のコンテンツを置きます。今回は、非常にシンプルなindex.htmlを作成しました。
<html> <head> <title>CroudFront Test</title> </head> <body> <h1>CroudFrontのみから参照できるページです。</h1> </body> </html>
S3バケット名(今回はcm-katsuki)をクリックして、ActionsボタンからUplodeを選択します。
アップロード画面でローカルで作成したindex.htmlをドラッグ&ドロップします。
アップロード対象としてindex.htmlがエントリされました。Start Uploadをクリックして、アップロードを開始します。
アップロードが完了すると、こちらの画面になります。メッセージが右側に表示され、バケット内にindex.htmlが追加されます。
index.htmlのプロパティを確認します。ファイル左のチェックボックスをクリックし、次にPropertiesをクリックします。S3へアクセスするURLが表示されますが、鍵のアイコンが付いているので、公開されていません。
設定確認
コンテンツが公開されていないことを確認します。先程のURLをクリックします。すると、Access Deniedと表示され、index.htmlの内容は表示されません。
ここで面倒臭くなって、コンテンツにMake Public操作を加えてしまうと、S3から直接アクセスできる状態になってしまいます。設定はこのままで、CloudFrontの設定に進みます。
CloudFrontの設定
ディストリビューションの作成
これから、CloudFrontのディストリビューションの設定を行います。AWS Management Consoleのトップに戻って、CloudFrontをクリックします。
Create Distributionをクリックします。
Webコンテンツの配信なので、WebリージョンのGet Startedをクリックします。
S3バケットをオリジンに設定する
まず、リージョン作成画面の一番上のOrigin Domain Nameをクリックし、先に作っておいたS3バケットを選択します。
オリジンアクセスアイデンティティの設定
ここからが今回のポイントです。Restrict Bucket Accessを選択し、オリジンアクセスアイデンティティを使用する設定にします。
オリジンアクセスアイデンティティは通常準備がありませんので、ここで新規作成(Create a New Identity)を選択し、オリジンアクセスアイデンティティの用途がわかるよう、オリジンアクセスアイデンティティに対するコメントを記入します。
更に、Yes, Update Bucket Policyを選択することで、この新規に作られたオリジンアクセスアイデンティティで、S3バケット内のオブジェクト読み取り許可を付与してくれます。
変更されたS3バケットポリシーは、オリジンアクセスアイデンティティ削除時には残ります。手動で削除して下さい。
【参考】オリジンアクセスアイデンティティを使用して Amazon S3 コンテンツへのアクセスを制限する - Amazon CloudFront 開発者ガイド (API Version 2014-01-31)
その他の設定は、デフォルトのままで構いません。一番下まで画面をスクロールし、Create Distributionをクリックします。
ClodFrontディストリビューションの設定反映は最大15分程掛かりますので、以下の操作は少し時間を置いて下さい。
設定確認
オリジンアクセスアイデンティティが作成されたかを確認します。Origin Access Identityをクリックします。
すると、オリジンアクセスアイデンティティの一覧が表示されます。オリジンアクセスアイデンティティIDは自動的に作成されているので、複数ある場合は、先の画面で入力したコメントと照らしあわせて下さい。ここでオリジンアクセスアイデンティティIDを確認しておいて下さい。
S3のバケットポリシーを確認します。S3の管理画面から、バケット名をクリックし、Propertiesをクリックすると、バケットポリシーの設定状況が確認できます。バケット作成直後とは異なり、Edit Bucket Policyと表記が変わっています。内容を確認するために、Edit Bucket Policyをクリックします。
パケットポリシーエディタが開いて、今回自動的に付与されたバケットポリシーを確認できます。指定したバケットに対して、自動的に作成されたオリジンアクセスアイデンティティIDでの読み取り(GetObject)設定が付与されています。
設定確認
先程、S3バケット上のコンテンツへの直接アクセスは拒否されることを確認しました。今度はCloudFront経由でコンテンツにアクセスできるか確認します。CroudFrontの管理画面で、ディストリビューションの左側のiボタンをクリックします。
CloudFrontディストリビューションへのアクセスURLが表示されるので、これをブラウザにコピー&ペーストします。
コンテンツはindex.htmlで作りましたので、ペーストしたURLの後ろに/index.htmlを追加します。すると、内容が正しく表記されます。
念の為、S3バケットへの直接アクセスもここで改めて試してみても良いでしょう。S3バケットポリシーが変わっても直接アクセスはできません。
おまけ:デフォルトルートオブジェクトの設定
先程はCloudFrontディストリビューションのURLにコンテンツ名を追記して、コンテンツを表示させました。これをデフォルト値に設定します。CloudFrontの管理画面から、CloudFrontディストリビューションのiボタンをクリックし、GeneralタブでEditボタンをクリックします。
CloudFrontディストリビューションの設定変更画面の中に、Default Root Objectフォームがあります。ここに、デフォルトで表示したいコンテンツ名を記入してください。今回は、index.htmlとしてみます。
そして改めてCloudFrontディストリビューションへのアクセスURLにアクセスします。今度は自動的にindex.htmlが付加されるため、コンテンツの内容が表示されます。
まとめ
S3バケット上のコンテンツを、CloudFrontのみからアクセスできるように設定する方法を紹介しました。最初にAWSドキュメントを読んだ時には、オリジンアクセスアイデンティティという、聞きなれない単語が理解できませんでしたが、実際に書かれている通りに操作して設定を眺めてみると、その動作原理を理解することができました。みなさんも是非試して頂ければと思います。